/**
 * 
 */
package com.jeearsenal.algorithm;

/**
 * @author monika
 *
 */
public class SignedArithmeticOperations {
	
	/**
	 * @author monika
	 */
	class SignedOperand {
		private boolean positive;
		private String magnitude;
		
		public SignedOperand(String signedValue) {
			positive = true;
			if(signedValue == "" || signedValue == null){
				magnitude = signedValue;
				return;
			}
			signedValue = signedValue.trim();
			char first = signedValue.charAt(0);
			if(first == '-'){
				positive = false;
				magnitude = signedValue.substring(1).trim();
			} else if(first == '+') {
				positive = true;
				magnitude = signedValue.substring(1).trim();
			} else {
				magnitude = signedValue.trim();
			}
		}
		
		public boolean isPositive(){
			return positive;
		}
		
		public void changeSign(){
			positive = !positive;
		}
		
		public String modulus() {
			return magnitude;
		}
		
		public String value(){
			if(positive){
				return magnitude;
			} else {
				return "-"+magnitude;
			}
		}
		
	}
	
	/**
	 * to add two signed numbers.
	 * 
	 * @param operand1
	 * @param operand2
	 * @return
	 */
	public String add(String operand1, String operand2) {
		SignedOperand op1 = new SignedOperand(operand1);
		SignedOperand op2 = new SignedOperand(operand2);
		String result = "";
		ArithmeticOperations calculator = new ArithmeticOperations();
		if(op1.isPositive()==true && op2.isPositive()==true) {
			result=calculator.add(op1.modulus(),op2.modulus());
		}
		else if(op1.isPositive()==false && op2.isPositive()==false)
		{
			result="-"+calculator.add(op1.modulus(),op2.modulus());
		}
		else
		{
			result=calculator.subtract(op1.modulus(), op2.modulus());
			if(result==null) {
				result=calculator.subtract(op2.modulus(), op1.modulus());
				if(op2.isPositive() == false){
					result = "-"+result;
				}
			}else {
				if(op1.isPositive() == false){
					result = "-"+result;
				}
			}
		}
		return makeUnsignedZero(result);
	}
	
	/**
	 * to perform  subtraction of two signed numbers.
	 * 
	 * @param operand1
	 * @param operand2
	 * @return
	 */
	public String subtract(String operand1, String operand2) {
		SignedOperand op1 = new SignedOperand(operand1);
		SignedOperand op2 = new SignedOperand(operand2);
		op2.changeSign();
		return add(op1.value(), op2.value());
	}
	
	/**
	 * to perform multiplication of two signed numbers.
	 * 
	 * @param operand1
	 * @param operand2
	 * @return
	 */
	public String multiply(String operand1, String operand2) {
		SignedOperand op1 = new SignedOperand(operand1);
		SignedOperand op2 = new SignedOperand(operand2);
		String result = "";
		ArithmeticOperations calculator = new ArithmeticOperations();
		result = calculator.multiply(op1.modulus(), op2.modulus());
		boolean positive = true;
		if( (op1.isPositive()== true && op2.isPositive()==false) || 
				(op1.isPositive() == false && op2.isPositive() == true)){
			positive = false;
		}
		
		if(positive == false){
			result = "-"+result;
		}
		return makeUnsignedZero(result);
	}
	
	/**
	 * to perform the division of two signed numbers.
	 * Example:
	 *   7 / 2 = [3, 1]
	 *   -7/-2= [3, -1]
	 *   -7/2 = [-3, -1]
	 *   7/-2 = [-3, 1]
	 *   
	 * @param dividend
	 * @param divisor
	 * @return array of two string elements. First being the quotient and second being remainder. 
	 * @throws ArithmeticException
	 */
	public String[] divide(String dividend, String divisor) throws ArithmeticException {
		SignedOperand op1 = new SignedOperand(dividend);
		SignedOperand op2 = new SignedOperand(divisor);
		String [] result;
		ArithmeticOperations calculator = new ArithmeticOperations();
		try {
			result = calculator.divide(op1.modulus(), op2.modulus());
		} catch (ArithmeticException e) {
			throw e;
		}
		boolean positive = true;
		
		if( (op1.isPositive()== true && op2.isPositive()==false) || 
				(op1.isPositive() == false && op2.isPositive() == true)){
			positive = false;
		}
		if(positive == false){
			result[0] = makeUnsignedZero("-"+result[0]);
			
		}
		if(op1.isPositive() == false){
			result[1] = makeUnsignedZero("-"+result[1]);
		}
		return result;
	}

	private String makeUnsignedZero(String value){
		if(value.equals("+0") || value.equals("-0")){
			return "0";
		}
		return value;
	}
}
